#!/usr/bin/env python3
"""
Three-Player Chessboard Drawing Script

This script draws a three-player chessboard layout with three 9×5 grids 
arranged in a triangular formation at 2π/3 radians (120-degree) angles.
Each board is a 9×5 grid in each player's domain.
"""

import matplotlib.pyplot as plt
import matplotlib.patches as patches
import numpy as np
import math

class ThreePlayerChessboard:
    def __init__(self, figsize=(12, 12)):
        self.fig, self.ax = plt.subplots(1, 1, figsize=figsize)
        self.cell_size = 0.8
        self.board_width = 4 * self.cell_size  # 5 columns = 4 intervals
        self.board_height = 8 * self.cell_size  # 9 rows = 8 intervals
        self.center = (0, 0)
        
        # Calculate the proper distance for adjacent boards
        self.board_distance = self.calculate_adjacent_distance()
        
        # Colors for each player's board
        self.board_colors = ['red', 'blue', 'green']
        self.board_labels = ['Player 1 (Red)', 'Player 2 (Blue)', 'Player 3 (Green)']
        
    def calculate_adjacent_distance(self):
        """Calculate the distance from center so boards are adjacent but not overlapping"""
        # For boards arranged at 120-degree angles, we want them to share a corner point
        # The diagonal of each board when rotated determines the minimum distance
        
        # Calculate the diagonal from center of board to corner
        half_width = self.board_width / 2
        half_height = self.board_height / 2
        board_diagonal = math.sqrt(half_width**2 + half_height**2)
        
        # For 120-degree spacing, adjacent boards will touch at their corners
        # The distance should be such that the sum of the distances from center
        # to the closest corners of adjacent boards equals the distance between 
        # those board centers times cos(60°)
        
        # Distance between board centers in equilateral triangle arrangement
        # For adjacent touching at corners: distance = board_diagonal / sin(60°)
        distance = board_diagonal / math.sin(math.radians(60))
        
        return distance
    
    def draw_single_board(self, center_x, center_y, rotation_angle, board_id):
        """Draw a single 9x5 grid board"""
        
        # Calculate board corner position (bottom-left)
        board_x = center_x - self.board_width / 2
        board_y = center_y - self.board_height / 2
        
        lines = []
        
        # Draw internal vertical lines only (exclude the outer borders)
        for i in range(1, 5):  # Skip first (0) and last (5) vertical lines
            x = board_x + i * self.cell_size
            y_start = board_y
            y_end = board_y + self.board_height
            lines.append([(x, y_start), (x, y_end)])
            
        # Draw internal horizontal lines only (exclude the outer borders)
        for i in range(1, 9):  # Skip first (0) and last (9) horizontal lines
            y = board_y + i * self.cell_size
            x_start = board_x
            x_end = board_x + self.board_width
            lines.append([(x_start, y), (x_end, y)])
        
        # Draw the outer perimeter separately
        perimeter_lines = [
            [(board_x, board_y), (board_x + self.board_width, board_y)],  # bottom
            [(board_x + self.board_width, board_y), (board_x + self.board_width, board_y + self.board_height)],  # right
            [(board_x + self.board_width, board_y + self.board_height), (board_x, board_y + self.board_height)],  # top
            [(board_x, board_y + self.board_height), (board_x, board_y)]  # left
        ]
        
        # Combine internal lines with perimeter
        all_lines = lines + perimeter_lines
        
        # Apply rotation to all lines
        rotated_lines = []
        for line in all_lines:
            rotated_line = []
            for point in line:
                rotated_point = self.rotate_point(point[0], point[1], center_x, center_y, rotation_angle)
                rotated_line.append(rotated_point)
            rotated_lines.append(rotated_line)
            
        # Draw the lines
        color = self.board_colors[board_id]
        for line in rotated_lines:
            x_coords = [point[0] for point in line]
            y_coords = [point[1] for point in line]
            self.ax.plot(x_coords, y_coords, color=color, linewidth=1.5)
    
    def rotate_point(self, x, y, center_x, center_y, angle_degrees):
        """Rotate a point around a center by given angle in degrees"""
        angle_rad = math.radians(angle_degrees)
        cos_angle = math.cos(angle_rad)
        sin_angle = math.sin(angle_rad)
        
        # Translate to origin
        x -= center_x
        y -= center_y
        
        # Rotate
        new_x = x * cos_angle - y * sin_angle
        new_y = x * sin_angle + y * cos_angle
        
        # Translate back
        new_x += center_x
        new_y += center_y
        
        return (new_x, new_y)
    
    def draw_connecting_lines(self):
        """Draw dashed lines extending from the middle of each board toward the center"""
        # Calculate positions for three boards (120 degrees apart)
        angles = [0, 120, 240]  # degrees
        
        # Central convergence point
        convergence_point = self.center
        
        for angle in angles:
            # Calculate board center position
            angle_rad = math.radians(angle)
            board_center_x = self.center[0] + self.board_distance * math.cos(angle_rad)
            board_center_y = self.center[1] + self.board_distance * math.sin(angle_rad)
            
            # Calculate the starting point on the board's inner edge (middle line)
            # The middle line runs through the center of the board facing the center
            edge_distance = min(self.board_width, self.board_height) / 2
            
            # Start point: from board center, move toward global center by edge distance
            toward_center_x = -edge_distance * math.cos(angle_rad)
            toward_center_y = -edge_distance * math.sin(angle_rad)
            
            start_point_x = board_center_x + toward_center_x
            start_point_y = board_center_y + toward_center_y
            
            # Draw dashed line from board's middle edge to central convergence point
            x_coords = [start_point_x, convergence_point[0]]
            y_coords = [start_point_y, convergence_point[1]]
            
            self.ax.plot(x_coords, y_coords, 'k--', linewidth=2, alpha=0.7)
        
        # Optionally add a small circle at the convergence point
        circle = plt.Circle(convergence_point, 0.3, color='black', alpha=0.5, fill=True)
        self.ax.add_patch(circle)
    
    def draw_boundary_connections(self):
        """Draw short dashed lines connecting adjacent corner points of neighboring boards"""
        # Calculate positions for three boards (120 degrees apart)
        angles = [0, 120, 240]  # degrees
        
        for i in range(3):
            current_angle = angles[i]
            next_angle = angles[(i + 1) % 3]
            
            # Calculate current board center position
            current_angle_rad = math.radians(current_angle)
            current_board_center_x = self.center[0] + self.board_distance * math.cos(current_angle_rad)
            current_board_center_y = self.center[1] + self.board_distance * math.sin(current_angle_rad)
            
            # Calculate next board center position  
            next_angle_rad = math.radians(next_angle)
            next_board_center_x = self.center[0] + self.board_distance * math.cos(next_angle_rad)
            next_board_center_y = self.center[1] + self.board_distance * math.sin(next_angle_rad)
            
            # For the current board, find the corner closest to the next board
            # Since boards are rotated (angle + 180), we need to account for rotation
            board_rotation = current_angle + 180
            
            # The four corners of the board relative to its center (before rotation)
            half_width = self.board_width / 2
            half_height = self.board_height / 2
            corners = [
                (half_width, half_height),    # top-right
                (-half_width, half_height),   # top-left  
                (-half_width, -half_height),  # bottom-left
                (half_width, -half_height)    # bottom-right
            ]
            
            # Rotate corners and find the one closest to next board
            min_distance = float('inf')
            closest_corner_current = None
            
            for corner in corners:
                rotated_corner = self.rotate_point(
                    current_board_center_x + corner[0], 
                    current_board_center_y + corner[1],
                    current_board_center_x, 
                    current_board_center_y, 
                    board_rotation
                )
                
                # Calculate distance to next board center
                dist = math.sqrt((rotated_corner[0] - next_board_center_x)**2 + 
                               (rotated_corner[1] - next_board_center_y)**2)
                
                if dist < min_distance:
                    min_distance = dist
                    closest_corner_current = rotated_corner
            
            # For the next board, find the corner closest to the current board
            next_board_rotation = next_angle + 180
            min_distance = float('inf')
            closest_corner_next = None
            
            for corner in corners:
                rotated_corner = self.rotate_point(
                    next_board_center_x + corner[0], 
                    next_board_center_y + corner[1],
                    next_board_center_x, 
                    next_board_center_y, 
                    next_board_rotation
                )
                
                # Calculate distance to current board center
                dist = math.sqrt((rotated_corner[0] - current_board_center_x)**2 + 
                               (rotated_corner[1] - current_board_center_y)**2)
                
                if dist < min_distance:
                    min_distance = dist
                    closest_corner_next = rotated_corner
            
            # Draw short dashed line connecting the closest corners
            if closest_corner_current and closest_corner_next:
                x_coords = [closest_corner_current[0], closest_corner_next[0]]
                y_coords = [closest_corner_current[1], closest_corner_next[1]]
                
                self.ax.plot(x_coords, y_coords, 'gray', linestyle='--', linewidth=1.5, alpha=0.6)
    
    def draw_three_player_board(self):
        """Draw the complete three-player chessboard"""
        
        # Calculate positions for three boards (120 degrees apart)
        angles = [0, 120, 240]  # degrees
        
        for i, angle in enumerate(angles):
            # Calculate board center position
            angle_rad = math.radians(angle)
            board_center_x = self.center[0] + self.board_distance * math.cos(angle_rad)
            board_center_y = self.center[1] + self.board_distance * math.sin(angle_rad)
            
            # Draw the board rotated to point toward center
            self.draw_single_board(board_center_x, board_center_y, angle + 180, i)
        
        # Draw connecting lines between the boards
        self.draw_connecting_lines()
        
        # Draw boundary connections between the boards
        self.draw_boundary_connections()
        
        # Add title
        # self.ax.text(0, -12, 'Three-Player Chessboard (9×5 grids)', 
        #             ha='center', va='center', fontsize=16, fontweight='bold')
        
        # Set equal aspect ratio and remove axes
        self.ax.set_aspect('equal')
        self.ax.set_xlim(-15, 15)
        self.ax.set_ylim(-15, 10)
        self.ax.axis('off')
        
        # Add grid if desired (optional)
        # self.ax.grid(True, alpha=0.3)
    
    def show(self):
        """Display the chessboard"""
        plt.tight_layout()
        plt.show()
    
    def save(self, filename='three_player_chessboard.png', dpi=300):
        """Save the chessboard to a file"""
        plt.tight_layout()
        plt.savefig(filename, dpi=dpi, bbox_inches='tight')
        print(f"Three-player chessboard saved as {filename}")

def main():
    """Main function to create and display the three-player chessboard"""
    board = ThreePlayerChessboard()
    board.draw_three_player_board()
    board.save()

if __name__ == "__main__":
    main() 